using System.Collections.Generic;
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public abstract class StorageBase
{
    [JsonProperty("storages")]
    private ObserveDictionary<string, StorageBase> _storages;

    [JsonIgnore]
    private string _key;

    [JsonIgnore]
    private bool _dirty;

    [JsonIgnore]
    private bool _init;

    /// <summary>
    /// 标记更新
    /// </summary>
    public void MarkDirty()
    {
        if (!_init)
            return;

        _dirty = true;
    }

    [JsonProperty(ProjectConfig.StroageKey)]
    public string Key
    {
        get
        {
            if (string.IsNullOrEmpty(_key))
                _key = GetType().FullName;
            return _key;
        }
    }

    /// <summary>
    /// 获取被标记的存档
    /// </summary>
    public void GetDirtyStorage(List<StorageBase> dirtyStorages)
    {
        if (_dirty)
        {
            dirtyStorages.Add(this);
            _dirty = false;
            return;
        }

        if (_storages == null || _storages.Count == 0)
            return;
        
        foreach(var storage in _storages.Values)
        {
            storage.GetDirtyStorage(dirtyStorages);
        }
    }

    /// <summary>
    /// 注册存档
    /// </summary>
    protected void RegisterStorage<T>() where T : StorageBase,new()
    {
        Type t = typeof(T);
        string key = t.FullName;

        if (_storages == null)
        {
            _storages = new ObserveDictionary<string, StorageBase>();
            _storages.TrySetAction(MarkDirty);
        }
            
        if (_storages.ContainsKey(key))
            return;

        _storages[key] = new T();
        _storages[key].Init();
    }

    public StorageBase GetStorage(string key)
    {
        if (Key.Equals(key))
            return this;

        if (_storages == null || _storages.Count == 0)
            return null;

        foreach(var storage in _storages.Values)
        {
            var result = storage.GetStorage(key);
            if (result != null)
                return result;
        }

        return null;
    }

    public void FromJson(string jsonData)
    {
        if (_storages == null || _storages.Count == 0)
            return;

        JObject jObject = JObject.Parse(jsonData);
        JToken storageToken = jObject.SelectToken("storages");
        foreach(var pair in _storages)
        {
            string fullName = pair.Key;
            StorageBase storage = pair.Value;
            string jsonStr = storageToken[fullName].ToString();
            JsonConvert.PopulateObject(jsonStr, storage);
            storage.FromJson(jsonStr);
        }
    }

    public void Init()
    {
        OnInit();
        _init = true;
    }

    public virtual void OnInit() {  }
}
